package com.slmxz.tms.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.slmxz.tms.biz.enums.OrderStatusEnum;
import com.slmxz.tms.biz.mapper.OrderDispatchMapper;
import com.slmxz.tms.biz.model.dto.OrderDispatchDTO;
import com.slmxz.tms.biz.model.entity.Order;
import com.slmxz.tms.biz.model.entity.OrderDispatch;
import com.slmxz.tms.biz.model.entity.OrderLifecycle;
import com.slmxz.tms.biz.service.OrderDispatchService;
import com.slmxz.tms.biz.service.OrderLifecycleService;
import com.slmxz.tms.biz.service.OrderService;
import com.slmxz.tms.common.component.NoGeneratorService;
import com.slmxz.tms.common.component.RedisUserService;
import com.slmxz.tms.common.enums.BizMessageEnum;
import com.slmxz.tms.common.util.LoggerUtil;
import com.slmxz.tms.core.exception.Asserts;
import com.slmxz.tms.core.exception.BizException;
import com.slmxz.tms.core.service.PrimaryKeySerivce;
import com.slmxz.tms.document.model.entity.Contractor;
import com.slmxz.tms.document.model.entity.Driver;
import com.slmxz.tms.document.model.entity.Truck;
import com.slmxz.tms.document.service.ContractorService;
import com.slmxz.tms.document.service.DriverService;
import com.slmxz.tms.document.service.TruckService;
import com.slmxz.tms.system.model.vo.UserInfoVO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单调度运输服务实现类
 *
 * @author sunyao
 *@Date 2025-04-02 21:14
 */
@Service
@RequiredArgsConstructor
public class OrderDispatchServiceImpl extends ServiceImpl<OrderDispatchMapper, OrderDispatch> implements OrderDispatchService, PrimaryKeySerivce<OrderDispatch> {

    private final ContractorService contractorService;
    private final DriverService driverService;
    private final OrderLifecycleService orderLifecycleService;
    private final OrderService orderService;
    private final TruckService truckService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dispatchOrder(OrderDispatchDTO orderDispatch) throws Exception{
        UserInfoVO user = RedisUserService.currentUser();
        //获取承运商
        Contractor contractor = this.contractorService.getById(orderDispatch.getContractorId());
        //获取司机
        Driver driver = this.driverService.getById(orderDispatch.getDriverId());
        //获取车辆
        Truck truck = this.truckService.getById(orderDispatch.getTruckId());
        //获取订单
        List<Order> orders = this.orderService.listByIds(orderDispatch.getOrderIds());
        //订单调度后的数据
        List<OrderDispatch> orderDispatchs = new ArrayList<>(orderDispatch.getOrderIds().size());
        //订单生命周期
        List<OrderLifecycle> orderLifecycles = new ArrayList<>(orderDispatch.getOrderIds().size());
        try{
            //生成调度编号
            String dispatchNo = NoGeneratorService.generatorNo("DB",10000);
            List<String> uncheckOrderNos = new ArrayList<>();
            //可以派遣的订单
            List<Order> orderParams = new ArrayList<>();
            //组装订单派遣数据，以及订单生命周期数据
            for(Order order : orders){
                OrderDispatch dispatchItem = new OrderDispatch();
                dispatchItem.setId(this.getId())
                        .setDispatchNo(dispatchNo)
                        .setContractorId(orderDispatch.getContractorId())
                        .setContractorName(contractor.getContractorName())
                        .setContractorType(contractor.getContractorType())
                        .setDriverName(driver.getDriverName())
                        .setDriverPhone(driver.getDriverPhone())
                        .setTruckNo(truck.getTruckNo())
                        .setTransportMode(orderDispatch.getTransportMode())
                        .setRouteId(orderDispatch.getRouteId())
                        .setPaySettleType(orderDispatch.getPaySettleType())
                        .setPayFareAmount(orderDispatch.getPayFareAmount())
                        .setOrderId(order.getId());
                orderDispatchs.add(dispatchItem);

                OrderLifecycle orderLifecycle = OrderLifecycle.builder()
                        .orderNo(order.getOrderNo())
                        .operateItem("订单调度")
                        .contentDesc("用户："+ user.getUsername() +",将订单调度给承运商："+ contractor.getContractorName()
                                +"(司机："+driver.getDriverName() + "/" + driver.getDriverPhone() + "-" + truck.getTruckNo()+")")
                        .build();
                orderLifecycles.add(orderLifecycle);

                if(!OrderStatusEnum.CHECK.getValue().equals(order.getOrderStatus())){
                    uncheckOrderNos.add(order.getOrderNo());
                    continue;
                }
                Order orderItem = new Order();
                //已派遣
                orderItem.setOrderStatus(OrderStatusEnum.DISPATCH.getValue());
                orderItem.setDispatchNo(dispatchNo);
                orderItem.setId(order.getId());
                orderParams.add(orderItem);
            }
            //是否存在没有被审核的订单
            Asserts.fail(CollectionUtils.isNotEmpty(uncheckOrderNos),BizMessageEnum.ORDER0000001,StringUtils.join(uncheckOrderNos,","));
            //批量保存
            this.saveBatch(orderDispatchs,100);
            //更新订单状态为已审核
            this.orderService.updateBatchById(orderParams,100);
            //更新订单生命周期
            this.orderLifecycleService.orderOperateRecord(orderLifecycles,user);
        }catch (Exception e){
            if(e instanceof BizException){
                throw e;
            }
            Asserts.fail(false, BizMessageEnum.BIZ0000002);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelDispatchOrder(OrderDispatchDTO orderDispatch) throws Exception {
        List<Long> orderIds = orderDispatch.getOrderIds();
        Asserts.fail(CollectionUtils.isEmpty(orderIds),BizMessageEnum.PARAM_IS_NULL);
        LoggerUtil.info(this,"开始撤销已派遣的订单,orderIds:{}",StringUtils.join(orderIds));
        UserInfoVO user = RedisUserService.currentUser();
        //查询订单
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.lambda().in(Order::getId,orderIds)
                .select(Order::getId,Order::getOrderNo,Order::getDispatchNo);
        List<Order> orders = this.orderService.list(orderQueryWrapper);
        //订单生命周期
        List<OrderLifecycle> orderLifecycles = new ArrayList<>(orders.size());
        orders.forEach(order -> {
            OrderLifecycle orderLifecycle = OrderLifecycle.builder()
                    .orderNo(order.getOrderNo())
                    .operateItem("撤销订单调度")
                    .contentDesc("用户："+ user.getUsername() +",取消订单调度")
                    .build();
            orderLifecycles.add(orderLifecycle);
        });
        List<String> dispatchNos =  orders.stream().map(Order::getDispatchNo).distinct().collect(Collectors.toList());
        try{
            //删除掉订单调度的数据
            QueryWrapper<OrderDispatch> dispatchQuery = new QueryWrapper<>();
            dispatchQuery.lambda().in(OrderDispatch::getDispatchNo,dispatchNos);
            this.remove(dispatchQuery);
            //更新订单状态到已审核
            orders.forEach(order -> {
                UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
                updateWrapper.lambda().set(Order::getOrderStatus,OrderStatusEnum.CHECK.getValue())
                        .set(Order::getDispatchNo,null)
                        .eq(Order::getId,order.getId());
                this.orderService.update(updateWrapper);
            });

            //更新订单生命周期
            this.orderLifecycleService.orderOperateRecord(orderLifecycles,user);
        }catch (Exception e){
            if (e instanceof BizException){
                throw e;
            }
            Asserts.fail(false, BizMessageEnum.BIZ0000002);
        }
    }
}
